//
//  NetworkTools.swift
//  testSwift
//
//  Created by miaozhihui on 2016/12/14.
//  Copyright © 2016年 DeKuTree. All rights reserved.
//

import UIKit
import AFNetworking

enum RequestMethod:String {
    case GET = "GET"
    case POST = "POST"
}

// MARK:网络工具
class NetworkTools: AFHTTPSessionManager {

    /// 网络请求回调，类似于 OC 的 typeDefine
    typealias RequestCallBack = (_ result:Any?,_ error:Error?)->()
    
    // 单例
    static let sharedTools:NetworkTools = {
        
        let tools = NetworkTools(baseURL: nil)
        tools.responseSerializer.acceptableContentTypes?.insert("text/plain")
        return tools
    }()
    
    /// 返回token字典
    fileprivate var tokenDict: [String:Any]? {
        // 判断token是否有效
        if let token = UserAccountViewModel.sharedUserAccount.accessToken {
            return ["access_token":token]
        }
        return nil
    }
    
    /// 用户账户的懒加载属性
    lazy var userAccount = UserAccount()
    
    /// 用户登录标记[计算型属性]
    var userLogon: Bool {
        return userAccount.access_token != nil
    }
    
    func tokenRequest(method:RequestMethod = .GET,URLString:String,parameters:[String:Any]?,finish:@escaping RequestCallBack) {
        // 判断 token 是否为 nil，为 nil 直接返回
        guard let token = userAccount.access_token else {
            // 发送通知，提示用户登录
            DispatchQueue.global().asyncAfter(deadline: .now()+0.5, execute: {
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserNeedLoginNotification), object: nil)
            })
            finish(nil, NSError(domain: "token为nil", code: -1, userInfo: nil))
            return
        }
        
        var params = parameters
        // 判断 参数字典 是否为 nil，为 nil 新建一个字典
        if params == nil {
            params = [String:Any]()
        }
        
        params!["access_token"] = token
        
        request(method: method, URLString: URLString, parameters: params, finished: finish)
    }
    
}

// MARK: - 用户相关方法
extension NetworkTools {
    
    /// 加载用户信息
    ///
    /// - Parameters:
    ///   - uid: uid
    ///   - finished: 完成回调
    /// - see:[http://open.weibo.com/wiki/2/users/show](http://open.weibo.com/wiki/2/users/show)
    func loadUserInfo(uid:String,finished:@escaping RequestCallBack) {
        let urlString = "https://api.weibo.com/2/users/show.json"
        let params = ["uid":uid]
        tokenRequest(URLString: urlString, parameters: params, finish: finished)
    }
}

// MARK: - OAuth相关方法
extension NetworkTools {
    
    /// OAuth 授权 URL
    /// - see:[http://open.weibo.com/wiki/Oauth2/authorize](http://open.weibo.com/wiki/Oauth2/authorize)
    var oauthURL:URL {
        let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(appKey)&redirect_uri=\(redirectUrl)"
        return URL(string: urlString)!
    }
    
    /// 加载AccessToken
    ///
    /// - Parameters:
    ///   - code: 授权码
    ///   - finished: 完成回调
    /// - see:[http://open.weibo.com/wiki/OAuth2/access_token](http://open.weibo.com/wiki/OAuth2/access_token)
    func loadAccessToken(code:String,finished:@escaping RequestCallBack) {
        let urlString = "https://api.weibo.com/oauth2/access_token"
        let params = ["client_id":appKey,"client_secret":appSecret,"grant_type":"authorization_code","code":code,"redirect_uri":redirectUrl]
        request(method: .POST, URLString: urlString, parameters: params, finished: finished)
    }
}

// MARK:封装AFN网络方法
extension NetworkTools {
    
    /// 网络请求
    ///
    /// - Parameters:
    ///   - method: GET/POST
    ///   - URLString: URLString
    ///   - parameters: 参数字典
    ///   - finished: 完成回调
    func request(method:RequestMethod, URLString:String,parameters:[String:Any]?,finished:@escaping RequestCallBack) {
        
        let success = { (task:URLSessionDataTask, result:Any?) in
            finished(result, nil)
        }
        
        let failure = { (task:URLSessionDataTask?, error:Error) in
            if (task?.response as? HTTPURLResponse)?.statusCode == 403 {
                // token 过期，把token清空
                self.userAccount.access_token = nil
                // 发送通知，Token 过期了 提示用户重新登录
                DispatchQueue.global().asyncAfter(deadline: .now()+0.5, execute: {
                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: WBUserNeedLoginNotification), object: "invalid token")
                })
            }
            print(error)
            finished(nil, error)
        }
        
        if method == .GET {
            get(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
        } else {
            post(URLString, parameters: parameters, progress: nil, success: success, failure: failure)
        }

    }
}
